import { _decorator, Collider2D, Component, Contact2DType, instantiate, IPhysics2DContact, math, Node, ParticleSystem2D, PhysicsGroup, PhysicsSystem2D, Prefab, RigidBody2D, Vec2 } from 'cc';
import Mgr from '../../manager/Mgr';
import MathUtils from '../../utils/MathUtils';
import { ShakeUtils } from '../../utils/ShakekUtils';
import { ShakeConst } from '../../utils/shake/ShakeConst';
import { PlayerVo } from '../vo/PlayerVo';
import { CacheManager } from '../../manager/CacheManager';
import { Enemy } from './Enemy';
import { EventManager } from '../../manager/EventManager';
import { EventEnum } from '../../enum/EventEnum';
import { BaseEntity } from './BaseEntity';
import { EyeController } from '../component/EyeController';
const { ccclass, property } = _decorator;

@ccclass('Player')
export class Player extends BaseEntity {
    @property(Node) body: Node = null;
    @property(Node) rotationNode: Node = null;
    @property(Node) faceNode: Node = null;
    @property(Collider2D) collider: Collider2D = null;
    @property(RigidBody2D) rigidbody: RigidBody2D = null;
    @property(Prefab) shootParticle: Prefab = null;
    @property(Prefab) killParticle: Prefab = null;
    @property(Prefab) mirrorPrefab: Prefab = null;
    private _eyeController: EyeController = null;
    private _curDir: math.Vec2;
    private _forceVec: math.Vec2;
    private _playerVo: PlayerVo;
    private _bulletTime:boolean;

    protected onLoad(): void {
        this._curDir = new math.Vec2();
        this._forceVec = new math.Vec2();
        this.collider.on(Contact2DType.BEGIN_CONTACT, this.beginContact, this);
        this._playerVo = CacheManager.game.playerVo;
    }

    public init() {
        this._playerVo = CacheManager.game.playerVo;
        this.node.active = true;
        this.node.setPosition(0, 500);
        this.rigidbody.linearVelocity = new Vec2(0, 0);
        this.rigidbody.enabled = true;
        this.collider.enabled = true;
        this.rigidbody.wakeUp();
        EventManager.addListener(EventEnum.onGameSpeedUpdate,this.onGameSpeedUpdate,this);
        this._eyeController = this.node.getComponent(EyeController);
        this._eyeController.running = true;
    }

    protected initComponent(){
    }

    update(deltaTime: number) {
        if(!CacheManager.game.isStart()){
            this.reset();
        }
        
        const velocity = this.rigidbody.linearVelocity;
        if(!this._bulletTime){
            if (velocity.length() > 0 && (velocity.x > 1 || velocity.y > 1)) {
                const angle = Math.atan2(velocity.y, velocity.x) * (180 / Math.PI);
                this._eyeController.updateEyeAngle(angle);
            }
        }
    }

    private onGameSpeedUpdate(){
        const speed = CacheManager.game.gameSpeed;
        this._bulletTime = speed != 1;
    }

    // 设置旋转角度
    public updateAngle(angle:number) {
        this.rotationNode.setRotationFromEuler(0, 0, angle);
        this._eyeController.updateEyeAngle(angle + 90);
    }

    private beginContact(selfCollider: Collider2D, otherCollider: Collider2D, contact: IPhysics2DContact) {
        if (selfCollider.node !== this.node) {
            return;
        }
        let tirggerName = PhysicsGroup[otherCollider.group];
        if (tirggerName == "enemy") {
            let enemy = otherCollider.node.getComponent(Enemy);
            if(enemy.isDead) return;

            let linearVel = this.rigidbody.linearVelocity.clone().normalize().multiplyScalar(200);
            linearVel.y = Math.abs(linearVel.y) + 100;

            this.rigidbody.linearVelocity = new Vec2(0, 0);
            this.rigidbody.applyLinearImpulseToCenter(linearVel, true);

            let particle = instantiate(this.killParticle);
            particle.setPosition(otherCollider.node.position);
            this.node.parent.addChild(particle);

            // ShakeUtils.shakeScene();
            enemy.death();
            EventManager.dispatch(EventEnum.OnEnemyDeath,enemy);
            Mgr.soundMgr.play(`boom1`, false);
            this._playerVo.hp += 10;
            // this.createMirror();

        }
        else if(tirggerName == "death"){
            CacheManager.game.gameOver();
        }
        // this.updateAngle();
    }

    public shoot(force: Vec2) {
        Mgr.soundMgr.play("cardSlide4", false);
        this._forceVec.x = force.x;
        this._forceVec.y = force.y;
        this.rigidbody.linearVelocity = new Vec2(0, 0);
        this.rigidbody.applyLinearImpulseToCenter(this._forceVec, true);

        let particle = instantiate(this.shootParticle);
        particle.setPosition(this.node.position);
        this.node.parent.addChild(particle);
        this._curDir.x = force.x;
        this._curDir.y = force.y;
        this._curDir.normalize();
    }

    private createMirror(){
        let mirror = instantiate(this.mirrorPrefab);
        mirror.setPosition(this.node.position);
        this.node.parent.addChild(mirror);
        this.scheduleOnce(()=>{
            mirror.getComponent(RigidBody2D).applyLinearImpulseToCenter(new Vec2(1000, 1000),true);
        },1)
        mirror.getComponent(Collider2D).on(Contact2DType.BEGIN_CONTACT, this.beginMirrorContact, this);
    }

    private beginMirrorContact(selfCollider: Collider2D, otherCollider: Collider2D, contact: IPhysics2DContact){
        if (PhysicsGroup[selfCollider.group] !== "ball") {
            return;
        }
        let tirggerName = PhysicsGroup[otherCollider.group];
        if (tirggerName == "enemy") {
            let enemy = otherCollider.node.getComponent(Enemy);
            if(enemy.isDead) return;
            enemy.death();
            EventManager.dispatch(EventEnum.OnEnemyDeath,enemy);
            Mgr.soundMgr.play(`boom1`, false);
            this._playerVo.hp += 10;
            selfCollider.node.destroy();
        }
    }

    public reset() {
        if(!this._playerVo) return;
        this._playerVo = null;
        this.rigidbody.sleep();
        this.rigidbody.enabled = false;
        this.collider.enabled = false;
        this.node.active = false;
        this.rigidbody.linearVelocity = new Vec2(0, 0);
        this.node.setPosition(0, 500);
        this._eyeController.running = false;
    }

}


